import os
import sys

class FacadeFactory:
    """
    This class provides an instantiation to the user application Facade.
    @author Danilo Torres
    """
    
    FILE_SEPARATOR = os.sep
    PARENT_DIR = os.path.pardir
    
    def getFacadeInstance(self, facade):
        """
        Returns an instance of the user application Facade from its 
        path which is passed as parameter.
        """
        if os.path.isfile(facade):
            packgeWithFacade = self.getCompleteFacade(facade)
        parts = packgeWithFacade.split(".")
        className = parts[-1]
        package = ".".join(parts)
        if not(package == ""):
            try:
                exec("from " + packgeWithFacade + " import " + className)
            except ImportError, e:
                self.importProjectFromFacade(facade)
                exec("from " + packgeWithFacade + " import " + className)
                
        return eval(className)()

    def importProjectFromFacade(self, facade):
        """
        Includes the user project into the PYTHONPATH environment variable.
        """
        path = os.path.dirname(facade)
        
        ### getting packages root dir
        while os.path.isfile(path + self.FILE_SEPARATOR + "__init__.py"):
            path = path + self.FILE_SEPARATOR + self.PARENT_DIR
            path = os.path.abspath(path)

        sys.path.append(path) ### Adds path to PYTHONPATH
        
    def getCompleteFacade(self, path):
        """
        Returns the complete name of the user application facade.
        """
        path = path.replace('.py', '')
        facade = os.path.basename(path)
        path = os.path.dirname(path)
        dirList = os.listdir(path)

        while 1:
            init = False
            for fname in dirList:
                if fname == '__init__.py':
                    facade = os.path.basename(path) + '.' + facade
                    path = os.path.dirname(path)
                    dirList = os.listdir(path)
                    init = True
            if not init:
                break
        return facade
